home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 134_01 / ctoa.c < prev    next >
Text File  |  1985-08-19  |  20KB  |  905 lines

  1. /*    CTOA -- BDS `C' CRL-to-ASM postprocessor- part 1.    */
  2.  
  3. /*
  4.     Kevin B. Kenny
  5.     729-A E. Cochise Dr.
  6.     Phoenix, AZ   85020
  7. */
  8.  
  9. /*    Copyright (c) 1983 by Kevin B. Kenny
  10.     Released to the BDS `C' Users' Group for non-commercial distribution
  11.     only. */
  12.  
  13. /*    This program is a utility that generates assembly language (.CSM)
  14.     source files for BDS `C' programs.  It accepts the .CRL file for the
  15.     object instructions, the .CDB file for the symbols, and the .C source
  16.     file for commentary.  From these, it produces a .CSM file that generate
  17.     the same object code.
  18.  
  19.     Syntax:
  20.         ctoa source_file [>output_file]
  21. */
  22.  
  23. #include <bdscio.h>
  24. #include <dio.h>
  25. #include <cmdutil.h>
  26. #include "ctoatbls.h"
  27. #include "ctoa.h"
  28.  
  29. #define TITLE "CTOA version 83-11-11 copyright (c) 1983 by Kevin Kenny.\n"
  30.  
  31. /*    Main program    */
  32.  
  33. main (argc, argv)
  34.     int argc;
  35.     char * * argv;
  36.     {
  37.     /* Check command syntax */
  38.  
  39.     dioinit (&argc, argv);
  40.     if (argc != 2) {
  41.         fprintf (STD_ERR, "Usage: ctoa filename [>outfile]\n");
  42.         quit ();
  43.         }
  44.     fprintf (STD_ERR, TITLE);
  45.  
  46.     /* Pick up the source file name, and open the source */
  47.  
  48.     strcpy (srcfnam, argv [1]);
  49.     if (fopen (srcfnam, srcfile) == ERROR) {
  50.         fprintf (STD_ERR, "Can't open %s: %s\n", srcfnam, 
  51.                     errmsg (errno ()));
  52.         quit ();
  53.         }
  54.  
  55.     /* Acquire the opcode table */
  56.  
  57.     opc_tabl = opctabl ();
  58.  
  59.     /* Go get the .CRL  and .CDB files */
  60.  
  61.     initcdb ();
  62.     initcrl ();
  63.  
  64.     /* Process the content of the .CRL file */
  65.  
  66.     proccrl ();
  67.  
  68.     /* Flush any remaining text from the source file, and close it. */
  69.  
  70.     while (!seof) sscan ();
  71.     printf ("\n\n\tend\n");
  72.     fclose (srcfile);
  73.     if (cdbopen) cclose (cdbfile);
  74.  
  75.     /* Flush out directed I/O */
  76.  
  77.     dioflush ();
  78.  
  79.     }
  80.  
  81. /*    Set up processing of the .CRL file for object text     */
  82.  
  83. initcrl() {
  84.  
  85.     /* Get the .CRL file name */
  86.  
  87.     strcpy (crlfnam, srcfnam);
  88.     makeext (crlfnam, "CRL");
  89.  
  90.     /* Open the .CRL file, and read in the directory from it */
  91.  
  92.     tcopen (crlfile, crlfnam);
  93.     tcseek (crlfile, 0, CABS, crlfnam);
  94.     tcread (crlfile, crldir, sizeof crldir, crlfnam);
  95.  
  96.     /* Print a heading on the CSM file indicating the file name and
  97.        compilation options. */
  98.  
  99.     printf (";\t%s\tBDS `C' object code of %s\n", crlfnam, srcfnam);
  100.     printf (";\t\t\tCompilation options:");
  101.     if (havecdb) printf (" -k");
  102.     if (crldir.crleflag == 0xBD)
  103.         printf (" -e %04x", crldir.crleloc);
  104.     printf ("\n");
  105.     printf (";\t\t\tExternals use %d (0x%04x) bytes.\n", 
  106.             crldir.crlelen, crldir.crlelen);
  107.     printf ("\n\tMACLIB\t<BDS.LIB>\n\n");
  108.     if (crldir.crleflag == 0xBD)
  109.         printf ("SYS$EXTFLAG\tSET\t0BDH\nSYS$EXTADDR\tSET\t0%04xH\n",
  110.                                  crldir.crleloc);
  111.     printf ("SYS$EXTSIZE\tSET\t0%04xH\n\n", crldir.crlelen);
  112.  
  113.     /*    Print non-library-defined CCC symbols on the .CSM file. */
  114.  
  115.     initccc ();
  116.     }
  117.  
  118. /*    Process the functions on a .CRL file    */
  119.  
  120. proccrl () {
  121.     union {            /* .CRL directory pointer */
  122.         char * c;
  123.         int * i;
  124.         } dirp;
  125.  
  126.     /* Point dirp to the start of the directory */
  127.  
  128.     dirp.c = & (crldir.crldtext);
  129.  
  130.     /* Walk through the directory, doing functions one by one */
  131.  
  132.     for (;;) {
  133.         strcpy70 (fname, dirp.c);    /* Get function name */
  134.         if (!*fname) break;        /* Return if end of file */
  135.         dirp.c += strlen (fname);    /* Advance directory pointer */
  136.         faddr = *dirp.i++;        /* Get function address */
  137.         procfunc ();            /* Process the function */
  138.         }
  139.     cclose (crlfile);        /* All done; close file */
  140.     }
  141.  
  142. /*    Do one function from a .CRL file    */
  143.  
  144. procfunc () {
  145.  
  146.     /* Announce ourselves */
  147.  
  148.     fprintf (STD_ERR, "; Processing the %s function:\n", fname);
  149.  
  150.     /* Find the function on the source and .CDB files. */
  151.  
  152.     sfunct (fname);
  153.     cdbfunct (fname);
  154.  
  155.     /* Put the FUNCTION statement on the .CSM file */
  156.  
  157.     printf ("\n\tFUNCTION\t%s\n\n", fname);
  158.  
  159.     /* Process the external references from the function */
  160.  
  161.     procexts ();
  162.  
  163.     /* Output the stack frame layout */
  164.  
  165.     doframe ();
  166.  
  167.     /* Read in the function text and relocation */
  168.  
  169.     if (!readfunc ()) {
  170.         fprintf (STD_ERR, ";*** Function is too large to analyze.\n");
  171.         fprintf (STD_ERR, ";*** Break it up and try again.\n");
  172.         }
  173.  
  174.     else {
  175.         /* Construct the label table */
  176.  
  177.         bldlbtab ();
  178.  
  179.         /* Output the code */
  180.  
  181.         asmcode ();
  182.  
  183.         /* Get rid of allocated memory */
  184.  
  185.         freefunc ();
  186.         }
  187.  
  188.     /* Find the end of the function on the source */
  189.  
  190.     sendfn ();
  191.  
  192.     /* Put the ENDFUNC statement on the .CSM file */
  193.  
  194.     printf (";\n\tENDFUNC\t\t%s\n;\n", fname);
  195.     }
  196.  
  197. /*    Process the external reference directory from a function on the
  198.     .CRL file */
  199.  
  200. procexts () {
  201.     int extdlen;        /* Length of the external directory */
  202.     char syname [NAMLEN];    /* Name of an external symbol */
  203.     char * xnamp;        /* Pointer to current char in name */
  204.  
  205.     /* Position to the start of the function's external directory */
  206.  
  207.     extdlen = 0;
  208.     tcseek (crlfile, faddr, CABS, crlfnam);
  209.  
  210.     nexts = 0;        /* No externals yet. */
  211.  
  212.     /* Read externals from the file */
  213.  
  214.     for (;;) {
  215.         xnamp = & syname;
  216.         tcread (crlfile, xnamp, 1, crlfnam); ++extdlen;
  217.                     /* Get first byte of external name */
  218.         if (syname [0] == '\0') break;
  219.                     /* If it's zero, we're done. */
  220.         while ((*xnamp & 0x80) == 0) {
  221.             tcread (crlfile, ++xnamp, 1, crlfnam); ++extdlen;
  222.             }        /* Read the rest of the symbol */
  223.         *xnamp &= 0x7F;        /* Strip the 7th bit from last char */
  224.         *++xnamp = 0;        /* Add null terminator */
  225.         printf ("\tEXTERNAL\t%s\n", syname);
  226.                     /* Put EXTERNAL statement on .CSM */
  227.         strcpy (xname [nexts++], syname);
  228.                     /* Install name in table */
  229.         }
  230.     
  231.     /* End of external directory */
  232.  
  233.     printf (";\n");
  234.     ftaddr = faddr + extdlen + 2;    /* Find function text */
  235.     }    
  236.  
  237. /*    Read the text and relocation of a function    */
  238.  
  239. readfunc () {
  240.  
  241.     /* Read in the length word for the function text */
  242.  
  243.     tcseek (crlfile, ftaddr-2, CABS, crlfnam);
  244.     tcread (crlfile, &ftlen, 2, crlfnam);
  245.  
  246.     /* Get space for the function text, and read it in. */
  247.  
  248.     if ((ftext = alloc (ftlen)) == NULL) return (FALSE);
  249.     tcread (crlfile, ftext, ftlen, crlfnam);
  250.  
  251.     /* Read in the size of the relocation info */
  252.  
  253.     tcread (crlfile, &frlen, 2, crlfnam);
  254.  
  255.     /* Read in the relocation data itself */
  256.  
  257.     if ((freloc = alloc (2 * frlen)) == NULL) {
  258.         free (ftext);
  259.         return (FALSE);
  260.         }
  261.     tcread (crlfile, freloc, 2 * frlen, crlfnam);
  262.  
  263.     /* Tell the user what happened */
  264.  
  265.     fprintf (STD_ERR, ";\t%d (0x%04x) bytes of text, ", ftlen, ftlen);
  266.     fprintf (STD_ERR, "%d relocation directives,\n", frlen);
  267.     fprintf (STD_ERR, ";\t%d external functions", nexts);
  268.     if (havecdb) {
  269.      fprintf (STD_ERR, ", %d external variables,\n", nextvs);
  270.      fprintf (STD_ERR, ";\t%d auto variables, %d formal parameters, ",
  271.                   nautvs,        nparvs);
  272.      fprintf(STD_ERR, "frame size is %d (0x%04x)\n", framesize, framesize);
  273.      }
  274.     else fprintf (STD_ERR, "\n");
  275.     return (TRUE);
  276.     }
  277.  
  278. /*    Make the label table for a function    */
  279.  
  280. bldlbtab () {
  281.  
  282.     nlabs = 0;            /* Clear out the label table */
  283.  
  284.     pass1 = TRUE;            /* We're doing the label pass */
  285.  
  286.     dotext ();            /* Analyze text for line #s. */
  287.  
  288.     doreloc ();            /* Get other labels from relocation */
  289.  
  290.     }
  291.  
  292. /*    Make the assembly code for a function    */
  293.  
  294. asmcode () {
  295.     
  296.     pass1 = FALSE;            /* We're doing the code pass */
  297.  
  298.     dotext ();            /* Output the instructions */
  299.  
  300.     dospool ();            /* Output the string pool */
  301.     }
  302.  
  303. /*    Walk through the instructions for a function    */
  304.  
  305. dotext () {
  306.     char * label;            /* Label on the current word */
  307.     struct opc_entry * opcent;
  308.  
  309.     /* Set up the initial location counter past the external header */
  310.  
  311.     if (nexts == 0) locctr = 0;
  312.     else locctr = 3 * nexts + 3;
  313.     retaddr = ftlen;        /* Dummy up a return address */
  314.     highcode = 0;            /* Dummy up a high transfer address */
  315.  
  316.     /* Walk through the instruction sequence */
  317.  
  318.     while (locctr < retaddr) {
  319.  
  320.         /* Look up the opcode */
  321.  
  322.         opcode = ftext [locctr];
  323.         for (    opcent = opc_tabl;
  324.             (opcode & opcent -> opc_mask) != opcent -> opc_val;
  325.             ++opcent) ;
  326.  
  327.         /* In code pass, output the opcode, and any label that
  328.            may be needed. */
  329.  
  330.         if (!pass1) {
  331.             if ((label = findlab (locctr)) != NULL)
  332.                 printf ("\n%s:", label);
  333.             if (opcent -> opc_type != OP_RST6)
  334.                 printf ("\t%s", opcent -